#include "StdAfx.h"
#include "RegManage.h"
#include <fstream>

#define MAX_NAME_LEN	256
#define MAX_DATA_LEN	2048
#define MAX_LEN			MAX_DATA_LEN

RegManage::RegManage(void)
{
}

RegManage::~RegManage(void)
{
}

void RegManage::Printf()
{
	for (RegKeyArrayIter iter = keyArray_.begin();iter != keyArray_.end();++iter)
	{
		iter->ToAllString();
	}
}

void RegManage::ReadReg(CString path, bool isIncludeSubKey)
{
	ReadRegKey(path,isIncludeSubKey);
}
void RegManage::WriteReg()
{
	for (RegKeyArrayIter iter = keyArray_.begin(); iter != keyArray_.end(); ++iter)
	{
		WriteRegKey(*iter);
	}
	keyArray_.clear();
}

void RegManage::ReadIni(CString path)
{
	using namespace std;
	wifstream wfin;
	wfin.open(path,ios::in);
	wchar_t *pFileBuf= new wchar_t[MAX_LEN/2];
	ZeroMemory(pFileBuf,MAX_LEN);

	while(wfin.getline(pFileBuf,MAX_LEN/2))
	{
		CString line;
		line.Format(L"%s",pFileBuf);
		ZeroMemory(pFileBuf,MAX_LEN);

		if (RegFormat::IsKey(line))
		{
			AddKey(_T(""));
			RegFormat::TextToKeyName(line,*curIter_);
		}
		else if (RegFormat::IsValue(line))
		{
			RegKeyValue regKeyValue;
			RegFormat::TextToValue(line,regKeyValue);
			curIter_->AddValue(regKeyValue);
		}
	}
}
void RegManage::WriteIni(CString path)
{
	using namespace std;
	wofstream wfout;
	wfout.open(path,ios::out);

	for (RegKeyArrayIter iter = keyArray_.begin();iter != keyArray_.end();++iter)
	{
		wfout<<iter->ToNameString().GetBuffer()<<_T('\n');
		for (size_t i=0;i<iter->GetValueSize();++i)
		{
			wfout<<iter->GetValue(i).ToString().GetBuffer()<<_T('\n');
		}
	}

	keyArray_.clear();
}

void RegManage::ReadRegKey(CString path,bool isIncludeSubKey)
{
	ReadRegValue(path);

	if (!isIncludeSubKey)
		return;

	HKEY hKey;
	DWORD dwDisposition;

	LONG res;
	res =RegCreateKeyEx(root_,path.GetBuffer(),0,NULL,0,
		0,NULL,&hKey,&dwDisposition);

	TCHAR keyName[MAX_NAME_LEN];
	DWORD keyNameLen = MAX_NAME_LEN;
	int index = 0;
	while (RegEnumKeyEx(hKey, index, keyName, &keyNameLen, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
	{
		CString subKey(keyName,keyNameLen);
		ReadRegKey(path +_T("\\") + subKey,isIncludeSubKey);
		++index;
		keyNameLen = MAX_NAME_LEN;
	}
	RegCloseKey(hKey);
}

void RegManage::ReadRegValue(CString path)
{
	AddKey(path);

	HKEY hKey;
	DWORD dwDisposition;

	LONG res;
	res =RegCreateKeyEx(root_,path.GetBuffer(),0,NULL,0,
		0,NULL,&hKey,&dwDisposition);

	int index = 0;
	TCHAR keyName[MAX_NAME_LEN];
	DWORD keyNameLen = MAX_NAME_LEN;
	BYTE keyValue[MAX_DATA_LEN];
	DWORD keyValueLen = MAX_DATA_LEN;
	DWORD valueType = 0;
	while (RegEnumValue(hKey, index, keyName, &keyNameLen, NULL, &valueType, keyValue, &keyValueLen) == ERROR_SUCCESS)
	{
		AddRegValue(keyName,valueType,keyValue,keyValueLen);
		++index;
		keyNameLen = MAX_NAME_LEN;
		keyValueLen = MAX_DATA_LEN;
	}

	RegCloseKey(hKey);
}

void RegManage::WriteRegKey(const RegKey& regKey)
{
	HKEY   hKey; 
	DWORD  dwDisposition;
	RegCreateKeyEx(root_,regKey.GetName().GetBuffer(),0,NULL,0,
		0,NULL,&hKey,&dwDisposition); 
	for (size_t i=0; i<regKey.GetValueSize();++i)
	{
		WriteRegKeyValue(hKey,regKey.GetValue(i));
	}
	RegCloseKey(hKey);
}

void RegManage::WriteRegKeyValue(HKEY hKey, const RegKeyValue& regKeyValue)
{
	switch(regKeyValue.GetType())
	{
	case RegTextType_Binary:
		{
			BYTE buf[4096];
			size_t realLen = 0;
			RegFormat::ValueDataToBinary(regKeyValue,buf,4096,realLen);
			RegSetValueEx(hKey,regKeyValue.GetName(),0,REG_BINARY,buf,realLen);
		}	
		break;
	case RegTextType_DWORD:
		{
			DWORD buf;
			RegFormat::ValueDataToDWORD(regKeyValue,buf);
			RegSetValueEx(hKey,regKeyValue.GetName(),0,REG_DWORD,(BYTE*)&buf,sizeof(DWORD));
		}
		break;
	case RegTextType_String:
		{
			CString buf;
			RegFormat::ValueDataToString(regKeyValue,buf);
			RegSetValueEx(hKey,regKeyValue.GetName(),0,REG_SZ,(BYTE*)buf.GetBuffer(),buf.GetLength()*sizeof(TCHAR));
		}			
		break;
	}
}

void RegManage::AddKey(CString path)
{
	RegKey key;
	key.SetName(path);
	keyArray_.push_back(key);
	curIter_ = --keyArray_.end();
}

void RegManage::AddRegValue(CString name, DWORD type, const BYTE* data, size_t len)
{
	RegKeyValue keyValue;
	keyValue.SetName(name);

	DWORD dwData;
	CString strData;
	bool isParser = false;
	switch(type)
	{
	case REG_DWORD:
		memcpy(&dwData,data,4);
		keyValue.SetType(RegTextType_DWORD);
		RegFormat::DWORDToValueData(dwData,keyValue);
		isParser = true;
		break;
	case REG_SZ:
		strData.Format(_T("%s"),data);
		keyValue.SetType(RegTextType_String);
		RegFormat::StringToValueData(strData,keyValue);
		isParser = true;
		break;
	case REG_BINARY:
		keyValue.SetType(RegTextType_Binary);
		RegFormat::BinaryToValueData(data,len,keyValue);
		isParser = true;
		break;
	default:
		isParser = false;
		GD_DBG_LOG("%s:%s false",curIter_->ToNameString(),name);
		break;
	}
	if (isParser)
		curIter_->AddValue(keyValue);
}